// SSE音频播放功能的jQuery封装
$(document).ready(function() {
  // 定义SSE音频播放器类
  class SSEAudioPlayer {
    constructor(options = {}) {
      // 默认配置
      this.config = {
        host: options.host || 'http://180.184.36.0:9101',
        endpoint: options.endpoint || '/tts',
        formSelector: '#ttsForm',
        submitBtnSelector: '#submitBtn',
        pauseBtnSelector: '#pauseBtn',
        replayBtnSelector: '#replayBtn',
        statusSelector: '#status',
        chunkInfoSelector: '#chunkInfo',
        currChunkSelector: '#currChunk',
        bgmSelector: '#bgm'
      };
      
      // 初始化
      this.init();
    }
    
    // 初始化函数
    init() {
      // 缓存DOM元素
      this.$form = $(this.config.formSelector);
      this.$submitBtn = $(this.config.submitBtnSelector);
      this.$pauseBtn = $(this.config.pauseBtnSelector);
      this.$replayBtn = $(this.config.replayBtnSelector);
      this.$status = $(this.config.statusSelector);
      this.$chunkInfo = $(this.config.chunkInfoSelector);
      this.$currChunk = $(this.config.currChunkSelector);
      this.$bgm = $(this.config.bgmSelector);
      this.bgm = this.$bgm.get(0);
      
      // 保存上一次的请求参数
      this.lastRequestParams = null;

      // 初始化音频相关变量
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
      this.audioQueue = [];
      this.isPlaying = false;
      this.isPaused = false;
      this.pausedPosition = 0;
      this.pausedBuffer = null;
      this.audioSource = null;
      this.isProcessing = false;
      this.currentChunkIndex = 0;
      this.totalPlaybackTime = 0;
      this.startTime = 0;
      this.bgmPausedTime = 0;
      // 初始化第一个数据提取相关的变量
      this.firstDataExtracted = false;
      this.firstDataUrl = null;
      this.firstDataWorkId = null;
      
      // 绑定事件
      this.bindEvents();
    }
    
    // 绑定事件
    bindEvents() {
      this.$form.on('submit', (e) => {
        e.preventDefault();
        this.startPlayback();
      });
      
      // 绑定暂停按钮事件
      this.$pauseBtn.on('click', (e) => {
        e.preventDefault();
        this.togglePause();
      });
      
      // 绑定重新播放按钮事件
      this.$replayBtn.on('click', (e) => {
        e.preventDefault();
        this.replayAudio();
      });
    }
    
    // 开始播放音频
    startPlayback() {
      // 获取表单数据
      const formData = this.getFormData();
      
      // 保存请求参数用于重新播放
      this.lastRequestParams = formData;
      
      // 启用重新播放按钮
      this.$replayBtn.prop('disabled', false).text('重新播放');
      
      // 准备播放环境
      this.preparePlayback();
      
      // 发送请求并处理音频流
      this.fetchAudioStream(formData);
    }
    
    // 获取表单数据
    getFormData() {
      return {
        speakerId: $('#speakerId').val(),
        uid: $('#uid').val(),
        artifactId: 2,
        text: $('#text').val()
      };
    }
    
    // 准备播放环境
    preparePlayback() {
      // 禁用提交按钮
      this.$submitBtn.prop('disabled', true).text('播放中...');
      
      // 启用暂停按钮
      this.$pauseBtn.prop('disabled', false).text('暂停播放');
      
      // 重新播放按钮保持启用状态，允许随时重新播放
      
      // 清空状态和音频信息
      this.$status.hide().empty();
      this.$chunkInfo.empty();
      this.$currChunk.empty();
      
      // // 初始化音频相关变量
      // this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
      // this.audioQueue = [];
      // this.isPlaying = false;
      // this.isPaused = false;
      // this.pausedPosition = 0;
      // this.pausedBuffer = null;
      // this.audioSource = null;
      // this.isProcessing = false;
      // this.currentChunkIndex = 0;
      // this.totalPlaybackTime = 0;
      // this.startTime = 0;
      // this.bgmPausedTime = 0;
    }
    
    // 更新状态显示
    updateStatus(message, className) {
      this.$status
        .text(message)
        .attr('class', 'status ' + className)
        .show();
    }
    
    // 格式化时间（秒）为mm:ss格式
    formatTime(seconds) {
      const mins = Math.floor(seconds / 60);
      const secs = Math.floor(seconds % 60);
      return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    }
    
    // 播放单个音频块
    async playAudioChunk(audioBuffer) {
      return new Promise((resolve) => {
        // 如果暂停状态下有缓存的位置，从暂停位置继续
        if (this.isPaused && this.pausedBuffer === audioBuffer) {
          // 停止之前的音频源
          if (this.audioSource) {
            this.audioSource.stop();
          }
          
          // 创建新的音频源
          this.audioSource = this.audioContext.createBufferSource();
          this.audioSource.buffer = audioBuffer;
          this.audioSource.connect(this.audioContext.destination);
          // 从暂停位置开始播放
          this.audioSource.start(0, this.pausedPosition);
          
          // 音频播放完成时的回调
          this.audioSource.onended = () => {
            // 更新总播放时间
            this.totalPlaybackTime += audioBuffer.duration;
            
            // 更新当前音频块索引
            this.currentChunkIndex++;
            
            // 更新当前音频块信息显示
            const formattedTime = this.formatTime(this.totalPlaybackTime);   
            console.log('当前播放时间  ： ',this.totalPlaybackTime);            
            this.$currChunk.text(`当前播放第 ${this.currentChunkIndex} 个音频块，已播放 ${formattedTime}`);
            
            this.isPaused = false;
            this.pausedBuffer = null;
            this.pausedPosition = 0;
            resolve();
          };
        } else {
          // 正常播放流程
          // 停止之前的音频源
          if (this.audioSource) {
            this.audioSource.stop();
          }
          
          // 创建新的音频源
          this.audioSource = this.audioContext.createBufferSource();
          this.audioSource.buffer = audioBuffer;
          this.audioSource.connect(this.audioContext.destination);
          
          // 如果是第一个音频块，记录开始时间
          if (this.startTime === 0) {
            this.startTime = this.audioContext.currentTime;
          }
          
          // 开始播放
          this.audioSource.start();
          
          // 音频播放完成时的回调
          this.audioSource.onended = () => {
            // 更新总播放时间
            this.totalPlaybackTime += audioBuffer.duration;
            
            // 更新当前音频块索引
            this.currentChunkIndex++;
            
            // 更新当前音频块信息显示
            const formattedTime = this.formatTime(this.totalPlaybackTime);
            console.log('当前播放时间  ： ',this.totalPlaybackTime);            

            this.$currChunk.text(`当前播放第 ${this.currentChunkIndex} 个音频块，已播放 ${formattedTime}`);
            
            resolve();
          };
        }
      });
    }
    
    // 处理音频队列
    async processAudioQueue() {
      if (this.isProcessing || this.audioQueue.length === 0 || this.isPaused) return;
      
      this.isProcessing = true;
      
      try {
        while (this.audioQueue.length > 0 && !this.isPaused) {
          const audioData = this.audioQueue.shift();
          // console.log('处理音频块--> ', audioData);
          try {
            // 解码音频数据
            const audioBuffer = await this.audioContext.decodeAudioData(audioData.slice(0));
            // 如果是第一个音频块，启动bgm
            if (this.currentChunkIndex === 0) {
              if (this.bgm) {
                this.bgm.currentTime = 0;
                this.bgm.play().catch(e => console.error('播放BGM失败:', e));
              }
            }
            // 播放音频块
            await this.playAudioChunk(audioBuffer);
            // 更新显示信息
            this.$chunkInfo.text(`已播放，队列中还有 ${this.audioQueue.length} 个音频块`);
            // 初始化当前音频块信息
            if (this.currentChunkIndex === 0) {
              this.currentChunkIndex = 1;
              const formattedTime = this.formatTime(audioBuffer.duration);
              this.$currChunk.text(`当前播放第 ${this.currentChunkIndex} 个音频块，已播放 ${formattedTime}`);
            }
          } catch (e) {
            console.error('解码或播放音频数据错误:', e);
          }
        }
      } finally {
        this.isProcessing = false;
        
        // 如果暂停但队列中还有数据，保存当前状态
        if (this.isPaused && this.audioQueue.length > 0) {
          this.$chunkInfo.text(`暂停中，队列中还有 ${this.audioQueue.length} 个音频块`);
        }
      }
    }
    
    // 播放第一个音频块
    async playFirstAudioChunk() {
      if (this.audioQueue.length > 0 && !this.isPlaying) {
        this.isPlaying = true;
        const audioData = this.audioQueue.shift();
        
        try {
          // 使用Promise.resolve确保正确的异步处理
          await Promise.resolve();
          
          // 解码音频数据（使用Promise包装）
          const audioBuffer = await new Promise((resolve, reject) => {
            this.audioContext.decodeAudioData(audioData.slice(0), resolve, reject);
          });
          
          // 启动bgm
          if (this.bgm) {
            this.bgm.currentTime = 0;
            this.bgm.play().catch(e => console.error('播放BGM失败:', e));
          }
          
          // 播放音频块
          await this.playAudioChunk(audioBuffer);
          
          // 更新显示信息
          this.$chunkInfo.text(`已播放，队列中还有 ${this.audioQueue.length} 个音频块`);
          
          // 继续处理剩余音频块
          this.processAudioQueue();
        } catch (e) {
          console.error('解码第一个音频块错误:', e);
        } finally {
          this.isPlaying = false;
        }
      }
    }
    
    // 解析Base64音频数据
    parseBase64AudioData(base64Data) {
      const binaryString = atob(base64Data);
      const bytes = new Uint8Array(binaryString.length);
      
      for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
      }      
      return bytes.buffer;
    }
    
    // 重置播放按钮状态
    resetButton() {
      this.$submitBtn.prop('disabled', false).text('开始播放');
      this.$pauseBtn.prop('disabled', true).text('暂停播放');
      this.$replayBtn.prop('disabled', false).text('重新播放'); // 启用重新播放按钮
      this.isPaused = false;
      this.pausedBuffer = null;
      this.pausedPosition = 0;
      this.currentChunkIndex = 0;
      this.totalPlaybackTime = 0;
      this.startTime = 0;
      this.bgmPausedTime = 0;
      this.$currChunk.empty();
      
      // 停止并重置bgm
      if (this.bgm) {
        this.bgm.pause();
        this.bgm.currentTime = 0;
      }
    }
    
    // 切换暂停/恢复状态
    togglePause() {
      if (!this.audioContext) return;
      
      if (this.isPaused) {
        // 从暂停状态恢复播放
        this.isPaused = false;
        this.$pauseBtn.text('暂停播放');
        this.updateStatus('正在播放...', 'connected');
        
        // 恢复播放bgm
        if (this.bgm) {
          try {
            // 确保在play()之前设置currentTime，保证从暂停位置开始播放
            // if (this.bgmPausedTime > 0) {
            //   this.bgm.currentTime = this.bgmPausedTime;
            //   console.log('背景音乐将从暂停位置恢复:', this.bgmPausedTime);
            // }
            this.bgm.play();
            console.log('背景音乐已恢复播放，当前位置:', this.bgm.currentTime);
          } catch (e) {
            console.error('播放BGM失败:', e);
          }
        }
        
        // 如果有暂停的缓冲区，继续播放当前缓冲区
        if (this.pausedBuffer) {
          this.playAudioChunk(this.pausedBuffer).then(() => {
            // 继续处理队列中的其他音频块
            this.processAudioQueue();
          });
        } else if (this.audioQueue.length > 0) {
          // 否则开始处理队列中的下一个音频块
          this.processAudioQueue();
        }
      } else {
        // 暂停播放
        this.isPaused = true;
        this.$pauseBtn.text('继续播放');
        this.updateStatus('已暂停', 'connected');
        
        // 暂停bgm并记录位置 - 无论是否有audioSource，都执行bgm暂停
        if (this.bgm) {
          try {
            this.bgmPausedTime = this.bgm.currentTime;
            this.bgm.pause();
            console.log('背景音乐已暂停，暂停位置:', this.bgmPausedTime);
          } catch (e) {
            console.error('暂停BGM失败:', e);
          }
        }
        
        // 记录当前播放位置并停止当前音频源
        if (this.audioSource && this.audioSource.buffer) {
          this.pausedPosition = this.audioContext.currentTime;
          this.pausedBuffer = this.audioSource.buffer;
          this.audioSource.stop();
          this.audioSource = null;
        }
        
        // 更新状态显示
        this.$chunkInfo.text(`暂停中，队列中还有 ${this.audioQueue.length} 个音频块`);
      }
    }
    
    // 获取音频流
    fetchAudioStream(formData) {
      const url = `${this.config.host}${this.config.endpoint}`;
      
      // 更新状态
      this.updateStatus('正在发送请求...', 'connecting');
      
      // 调试信息
      console.log('发送请求到:', url);
      console.log('请求体:', JSON.stringify(formData));
      
      // 发送POST请求
      fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'text/event-stream',
          'sign': '59ff66d0798de2ca415f03b22f6b22d4',
          'Cache-Control': 'no-cache'
        },
        body: JSON.stringify(formData)
      })
      .then(response => {
        // 记录响应信息
        console.log('响应状态:', response.status);
        console.log('响应头:', [...response.headers.entries()]);
        
        // 更新状态
        this.updateStatus('正在接收音频数据...', 'connected');
        
        // 处理SSE流
        this.processSSEStream(response);
      })
      .catch(error => {
        // 处理请求错误
        this.updateStatus('请求错误: ' + error.message, 'error');
        this.resetButton();
      });
    }
    
    // 处理SSE流
    processSSEStream(response) {
      const reader = response.body.getReader();
      const decoder = new TextDecoder('utf-8');
      let buffer = '';
      const self = this;
      
      // 读取流的函数
      function readStream() {
        reader.read().then(({ done, value }) => {
          if (done) {
            console.log('流结束',value);
            // 流结束
            self.updateStatus('流结束', 'connected');
            //self.resetButton();          
            // 处理剩余音频
            self.processAudioQueue();
            return;
          }
          
          // 解码并添加到缓冲区
          buffer += decoder.decode(value, { stream: true });
          
          // 处理缓冲区中的数据
          self.processBufferData(buffer, function(remainingBuffer) {
            buffer = remainingBuffer;
            // 继续读取
            readStream();
          });
        }).catch(error => {
          // 处理读取错误
          self.updateStatus('接收数据错误: ' + error.message, 'error');
          self.resetButton();
        });
      }
      
      // 开始读取流
      readStream();
    }
    
    // 处理缓冲区数据
    processBufferData(buffer, callback) {
      const lines = buffer.split('\n');
      const remainingBuffer = lines.pop();
      
      // 处理每一行
      for (const line of lines) {
        if (line.startsWith('data: ')) {
          // 处理数据行，只有当还未提取第一个数据块时才传递isFirstData=true
          const isFirstData = !this.firstDataExtracted;
          this.handleDataLine(line, isFirstData);
        } else if (line === 'event: end') {
          this.handleEndEvent();
        }
      }
      
      // 回调处理剩余缓冲区
      callback(remainingBuffer);
    }
    
    // 处理数据行
    handleDataLine(line, isFirstData = false) {
      const data = line.slice(6); // 移除 'data: ' 前缀
      
      try {
        // 检查数据有效性
        if (!data || data.trim() === '') {
          console.warn('接收到空数据块');
          return;
        }
        
        console.log('处理数据行:', data.substring(0, 100) + '...'); // 日志截断，避免过长
        
        // 尝试解析JSON数据
        let audioData;
        let extractedUrl = null;
        let extractedWorkId = null;
        
        try {
          const jsonData = JSON.parse(data);
          console.log('成功解析JSON数据，包含的键:', Object.keys(jsonData));
          
          // 寻找audioData字段，可能在不同位置
          audioData = jsonData.audioData || jsonData.data || data;
          
          // 如果是第一个数据块且尚未提取过，尝试提取url和workId
          if (isFirstData && !this.firstDataExtracted) {
            // 检查所有可能的字段名和路径
            // 直接检查根对象
            if (jsonData.url) {
              extractedUrl = jsonData.url;
              console.log('从根对象提取到URL:', extractedUrl);
            } else if (jsonData.data && jsonData.data.url) {
              extractedUrl = jsonData.data.url;
              console.log('从data.url提取到URL:', extractedUrl);
            } else if (jsonData.result && jsonData.result.url) {
              extractedUrl = jsonData.result.url;
              console.log('从result.url提取到URL:', extractedUrl);
            }
            
            // 提取workId
            if (jsonData.workId) {
              extractedWorkId = jsonData.workId;
              console.log('从根对象提取到workId:', extractedWorkId);
            } else if (jsonData.data && jsonData.data.workId) {
              extractedWorkId = jsonData.data.workId;
              console.log('从data.workId提取到workId:', extractedWorkId);
            } else if (jsonData.result && jsonData.result.workId) {
              extractedWorkId = jsonData.result.workId;
              console.log('从result.workId提取到workId:', extractedWorkId);
            }
            
            // 保存到实例属性
            if (extractedUrl) this.firstDataUrl = extractedUrl;
            if (extractedWorkId) this.firstDataWorkId = extractedWorkId;
            
            // 无论是否找到，都标记已提取过第一个数据块
            this.firstDataExtracted = true;
            
            // 派发事件通知外部代码，即使没有找到也派发，方便调试
            console.log('派发firstDataExtracted事件:', { url: extractedUrl, workId: extractedWorkId });
            $(document).trigger('firstDataExtracted', { url: extractedUrl, workId: extractedWorkId });
          }
          
          if (jsonData.frameType) {
            console.log('帧类型:', jsonData.frameType);
          }
        } catch (jsonError) {
          // 非JSON格式，直接作为Base64处理
          audioData = data;
          console.warn('无法解析为JSON格式，错误信息:', jsonError.message, '作为纯音频数据处理');
          
          // 即使是非JSON格式，也要标记第一个数据块已处理
          if (isFirstData && !this.firstDataExtracted) {
            this.firstDataExtracted = true;
            console.log('第一个数据块为非JSON格式，无法提取URL和workId');
            // 派发事件通知外部代码
            $(document).trigger('firstDataExtracted', { url: null, workId: null });
          }
        }
        
        // 检查音频数据
        if (!audioData || audioData.trim() === '') {
          console.warn('接收到空音频数据');
          return;
        }
        
        // 解析音频数据并加入队列
        const audioBuffer = this.parseBase64AudioData(audioData);
        this.audioQueue.push(audioBuffer);
        
        // 更新显示
        this.$chunkInfo.text(`已接收 ${this.audioQueue.length} 个音频块`);
        
        // 根据队列状态决定是否播放
        if (this.audioQueue.length === 1 && !this.isPlaying && !this.isProcessing) {
          this.playFirstAudioChunk();
        } else if (this.isPlaying && !this.isProcessing) {
          this.processAudioQueue();
        }
      } catch (e) {
        console.error('处理音频块错误:', e);
        console.error('有问题的数据:', data.substring(0, 200) + '...'); // 日志截断，避免过长
      }
    }
    
    // 处理结束事件
    handleEndEvent() {
      console.log('处理音频播放结束事件');
      
      // 停止bgm
      if (this.bgm) {
        try {
          console.log('音频播放结束，停止背景音乐');
          this.bgm.pause();
          this.bgm.currentTime = 0;
          this.bgmPausedTime = 0;
        } catch (e) {
          console.error('停止BGM失败:', e);
        }
      }
      
      this.updateStatus('音频播放完成', 'connected');
      this.resetButton();
      
      // 确保所有音频块都已播放
      if (!this.isProcessing && this.audioQueue.length > 0) {
        this.processAudioQueue();
      }
      
      // 音频流读取完成，派发loadCom事件
      console.log('音频流读取完成，派发loadCom事件');
      $(document).trigger('loadCom');
      
      // 音频播放完成，派发playCom事件
      console.log('音频播放完成，派发playCom事件');
      $(document).trigger('playCom');
    }
    
    // 重新播放音频
    replayAudio() {
      // 检查是否有保存的请求参数
      if (!this.lastRequestParams) {
        this.updateStatus('没有可重新播放的音频', 'error');
        return;
      }
      
      console.log('执行重新播放操作');
      
      // 停止当前正在播放的音频
      if (this.audioSource) {
        try {
          this.audioSource.stop();
        } catch (e) {
          console.warn('停止音频源时出错:', e);
        }
        this.audioSource = null;
      }
      
      // 清空音频队列
      this.audioQueue = [];
      
      // 重置音频相关状态
      this.isPlaying = false;
      this.isPaused = false;
      this.isProcessing = false;
      this.currentChunkIndex = 0;
      this.totalPlaybackTime = 0;
      this.startTime = 0;
      
      // 准备播放环境
      this.preparePlayback();
      
      // 使用保存的参数重新发送请求
      this.fetchAudioStream(this.lastRequestParams);
    }
  }
  
  // 创建并初始化音频播放器实例
  window.sseAudioPlayer = new SSEAudioPlayer();
});
